#include "basic.h"
#include "struct.h"
#include <gst/gst.h>


//==============================================================================DATA
static GstElement *playbin;
static GstBus *bus;
static GstMessage *msg;
static char uri[7+256] = "file://";


static gboolean bus_callback(GstBus *bus, GstMessage *msg, status_s *status);
//==============================================================================LIB INTERFACE
int openup(){
	
	gchar *version = gst_version_string();
	printf( "\n\nnow using GStreamer...version: %s\n", version+10);
	free( version );
	
	gst_init( NULL, NULL );
	playbin = gst_element_factory_make( "playbin2", "playbin" );
	bus = gst_pipeline_get_bus( GST_PIPELINE(playbin) );
	gst_object_unref(bus);

	return EXIT_SUCCESS;
}

int config( entry_s *ety ){
	return EXIT_SUCCESS;
}

int closedown(){
	gst_element_set_state( playbin, GST_STATE_NULL );
	gst_object_unref(GST_OBJECT (playbin));
	return EXIT_SUCCESS;
}

int operate( entry_s *ety, control_e control, status_s *status ){
	GstState gst_state;
	GstFormat gst_format = GST_FORMAT_TIME;
	bool mute;
	double volume;
	long position;

	switch( control ){
		case START: 
						if( !(status->flags & PAUSED) ){
							gst_element_set_state( playbin, GST_STATE_NULL );
							uri[7] = '\0';
							g_object_set( G_OBJECT(playbin), "uri", strcat( uri, ety->name ), NULL);							
						}
						gst_element_set_state( playbin, GST_STATE_PLAYING );
						status->flags |= AVOID_POST_PROCESSING;
						break;
		case STOP: 
						gst_element_set_state( playbin, GST_STATE_NULL );
						status->flags |= AVOID_POST_PROCESSING;						
						break;
		case PAUSE: 
						gst_element_set_state( playbin, GST_STATE_PAUSED );
						status->flags |= AVOID_POST_PROCESSING;
						break;
		case GONE:	
						/*清除旧的播放状态。重新读取状态*/
						status->flags &= ~0xFF;
			
						if( (msg = gst_bus_pop(bus)) != NULL ){
							bus_callback( bus, msg, status);
							gst_message_unref(msg);
							if( (status->flags & EOS) || (status->flags & ERROR) ) break;
						}
			
						gst_element_get_state( playbin, &gst_state, NULL, 1 );
						if( gst_state == GST_STATE_PLAYING ){
							status->flags |= PLAYING;
							status->now_playing = ety;
						}
						//if( gst_state == GST_STATE_READY ) state->type = PLAYING;
						//if( gst_state == GST_STATE_VOID_PENDING ) state->type = PLAYING;
						if( gst_state == GST_STATE_NULL ){
							status->flags |= STOPPED;
							status->now_playing = NULL;
						}
						if( gst_state == GST_STATE_PAUSED ) status->flags |= PAUSED;
						g_object_get( G_OBJECT(playbin), "mute", &mute, "volume", &volume, NULL);
						status->mute_on = mute;
						status->volume = (int)(volume * 1000);
						if( status->now_playing != NULL ){						
							gst_element_query_position( playbin, &gst_format, &position);
							status->position = position / (status->now_playing->duration);
						}else status->position = 0;
						break;
		case VOLUME:
						g_object_set( G_OBJECT(playbin), "mute", status->mute_on, NULL);
						volume = (double)status->volume / 1000;
						g_object_set( G_OBJECT(playbin), "volume", volume, NULL );
						status->flags |= AVOID_POST_PROCESSING;
						break;
		case SEEK:
						if( status->now_playing != NULL ){
							position = status->position * (status->now_playing->duration);
							gst_element_seek_simple( playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position);
						}
						status->flags |= AVOID_POST_PROCESSING;
						break;
		default : 
						break;

	}
	return EXIT_SUCCESS;
}

bool do_you_need_to_decode(){
	return FALSE;
}

bool do_you_need_to_configure(){
	return FALSE;
}

//------------------------------------------------------------------------------
static gboolean bus_callback(GstBus *bus, GstMessage *msg, status_s *status){
	
	switch (GST_MESSAGE_TYPE (msg)) {
		case GST_MESSAGE_EOS:
						g_print ("End-Of-Stream\n");
						status->flags |= EOS;
						break;
		case GST_MESSAGE_ERROR:{				
						gchar *debug;
						GError *err;
						gst_message_parse_error (msg, &err, &debug);
						g_free (debug);
						g_print ("Error: %s\n", err->message);
						g_error_free (err);									
						status->flags |= ERROR;
						gst_element_set_state( playbin, GST_STATE_NULL );
						break;
					}
		default: break;
	}
	
	return TRUE;
}